package http

import (
	"encoding/json"
	"net/http"
	"strconv"
	"strings"
)

const (
	SignName = "sign"
)

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
func CollectRequestParams(r *http.Request) (params map[string]string) {
	params = make(map[string]string)
	for k, v := range r.Form {
		params[k] = v[0]
	}
	return
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
type URLRequest struct {
	Sign string `json:"sign"`
}

func NewURLRequest() *URLRequest {
	return &URLRequest{}
}

func (req *URLRequest) UnmarshalFromRequest(r *http.Request, validSign string) (requestParams map[string]string, err error) {
	err = r.ParseForm()
	if err != nil {
		err = NewParseFormFail(err)
		return
	}

	requestParams = CollectRequestParams(r)

	if validSign != "" {
		sign, ok := requestParams[SignName]
		if !ok || sign != validSign {
			err = NewErrInvalidSign(sign, validSign)
			return
		}
		req.Sign = sign
	}

	return
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
func ParseIntRequestParam(requestParams map[string]string, requestParamName string, must bool) (requestParam int, err error) {
	s, ok := requestParams[requestParamName]
	if !ok || s == "" {
		if must {
			err = NewErrInvalidParam(requestParamName, s)
			return
		}
	} else {
		requestParam, err = strconv.Atoi(s)
		if err != nil {
			err = NewErrConvert2NumFail(s, err)
			return
		}
	}
	return
}

func ParseIntSliceRequestParam(requestParams map[string]string, requestParamName string, must bool) (requestParam []int, err error) {
	s, ok := requestParams[requestParamName]
	if !ok || s == "" {
		if must {
			err = NewErrInvalidParam(requestParamName, s)
			return
		}
	} else {
		var words = strings.Split(s, "|")
		for _, word := range words {
			i, e := strconv.Atoi(word)
			if e != nil {
				err = NewErrConvert2NumFail(word, e)
				return
			}
			requestParam = append(requestParam, i)
		}
	}
	return
}

func ParseStringRequestParam(requestParams map[string]string, requestParamName string, must bool) (requestParam string, err error) {
	var ok bool
	requestParam, ok = requestParams[requestParamName]
	if !ok || requestParam == "" {
		if must {
			err = NewErrInvalidParam(requestParamName, requestParam)
			return
		}
	}
	return
}

func ParseString2StringMapRequestParam(requestParams map[string]string, requestParamName string, must bool) (requestParam map[string]string, err error) {
	requestParam = map[string]string{}
	s, ok := requestParams[requestParamName]
	if !ok || s == "" {
		if must {
			err = NewErrInvalidParam(requestParamName, s)
			return
		}
	} else {
		kvs := strings.Split(s, "|")
		for _, s := range kvs {
			kv := strings.Split(s, ":")
			k := kv[0]
			if len(kv) > 1 {
				requestParam[k] = kv[1]
			} else {
				requestParam[k] = ""
			}
		}
	}
	return
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
type Response struct {
	Sign         string `json:"sign"`
	ErrorCode    int    `json:"error_code"`
	ErrorMessage string `json:"error_msg"`
}

func NewResponse() *Response {
	return &Response{}
}

func (resp *Response) Marshal() string {
	ba, _ := json.Marshal(resp)
	return string(ba)
}
